#include "search.hpp"
#include "fs.hpp"
#include "common.hpp"

void Enumerator::enumDir(QString path)
{
	log("Enumerator: enum '%s' \n", path.toLocal8Bit().data() );
	
	//iterator
	QStringList::iterator it;
	
	//deal with files
	QStringList files = fs->entryList(path, QDir::Files);
	for(it = files.begin(); it != files.end(); it++){
		this->files->append( path + QDir::separator() + *it );
	}

	//deal with dirs
	QStringList dirs = fs->entryList(path, QDir::Dirs);
	for(it = dirs.begin(); it != dirs.end(); it++){
		enumDir(path + QDir::separator() + *it);
	}
}

void Enumerator::run()
{
	files->clear();
	QStringList::iterator it;
	for(it = dirs->begin(); it != dirs->end(); it++){
		enumDir(*it);
	}
}

#define SEARCH_BLOCK 1024*1024
#define CONTEXT_BYTES 10

void Search::searchFile(QString path)
{
	QByteArrayMatcher match(key.regexp.toLocal8Bit());
	QByteArray buf(SEARCH_BLOCK, 0);
	size_t offset = 0;
	int readed = 0;
	do{
		//read
		readed = fs->read(path, buf.data(), SEARCH_BLOCK, offset);
		if(!readed) break;
		offset += readed;
		
		//find
		int index = 0;
		do{
			index = match.indexIn(buf, index);
			//found, add hit
			if( index != -1 ){
				hit.k = key;
				hit.path = path;
				int from = (index > CONTEXT_BYTES) ? (index - CONTEXT_BYTES) : 0;
				int size = CONTEXT_BYTES*2 + key.regexp.length();
				size = (size > (buf.size() - from)) ? (buf.size() - from) : size;
				hit.context = QString::fromLocal8Bit( &buf.data()[from], size ).simplified();
				hits->append(hit);
				emit hitFound(&hit);
				log("Search: hit file '%s', index %d, context %s\n",
					path.toLocal8Bit().data(), index, hit.context.toLocal8Bit().data());
				index++;
			}
		}while(index != -1);

	}while(readed > 0);
}

void Search::run()
{
	int pos = 0;
	QList<QString>::iterator it;
	for(it = files->begin(); it != files->end(); it++, pos++){
		searchFile(*it);
		emit fileSearched(pos);
	}
}
